﻿using DDD.Domain;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DDD.EFCore
{
    public abstract class Repository<TDbContext, TEntiy> : IRepository<TDbContext, TEntiy>
        where TDbContext : EFContext<TDbContext>
        where TEntiy : Entity, IAggregateRoot
    {
        protected virtual TDbContext DbContext { get; set; }

        protected Repository(TDbContext DbContext)
        {
            this.DbContext = DbContext;
        }

        public virtual IUnitOfWork UnitOfWork => DbContext;

        public System.Linq.IQueryable<TEntiy> GetAll()
        {
            return DbContext.Set<TEntiy>().Where(e => e.IsDeleted == false);
        }

        public virtual TEntiy Add(TEntiy entity)
        {
            return DbContext.Add(entity).Entity;
        }

        public virtual Task<TEntiy> AddAsync(TEntiy entity, CancellationToken cancellationToken = default)
        {
            return Task.FromResult(Add(entity));
        }

        public virtual TEntiy Update(TEntiy entity)
        {
            return DbContext.Update(entity).Entity;
        }

        public virtual Task<TEntiy> UpdateAsync(TEntiy entity, CancellationToken cancellationToken = default)
        {
            return Task.FromResult(Update(entity));
        }

        public virtual bool Remove(TEntiy entity)
        {
            return DbContext.Remove(entity).Entity != null;
        }

        public virtual Task<bool> RemoveAsync(TEntiy entity, CancellationToken cancellationToken = default)
        {
            return Task.FromResult(Remove(entity));
        }
    }

    public abstract class Repository<TDbContext, TEntiy, TKey> : Repository<TDbContext, TEntiy>, IRepository<TDbContext, TEntiy, TKey>
        where TDbContext : EFContext<TDbContext>
        where TEntiy : Entity<TKey>, IAggregateRoot
        //where TKey : IKey
    {
        protected Repository(TDbContext DbContext) : base(DbContext)
        {

        }

        public virtual System.Linq.IQueryable<TEntiy> AsQueryable()
        {
            return DbContext.Set<TEntiy>().AsQueryable();
        }

        public virtual bool Remove(TKey Id)
        {
            var entity = DbContext.Find<TEntiy>(Id);
            if (entity == null)
            {
                return true;
            }
            return DbContext.Remove(entity).Entity != null;
        }

        public virtual Task<bool> RemoveAsync(TKey Id, CancellationToken cancellationToken = default)
        {
            return Task.FromResult(Remove(Id));
        }

        public virtual TEntiy? Get(TKey Id)
        {
            return DbContext.Find<TEntiy>(Id);
        }

        public virtual async Task<TEntiy?> GetAsync(TKey Id, CancellationToken cancellationToken = default)
        {
            return await DbContext.FindAsync<TEntiy>(Id);
        }
    }


}
